import * as crypto from 'crypto';
import * as dayjs from 'dayjs';
import * as utc from 'dayjs/plugin/utc';
import Snowflake from 'snowflake-id';

dayjs.extend(utc);

const snowflake = new Snowflake({
  mid: 44,
  offset: (2019 - 1970) * 31536000 * 1000,
});

/**
 * 生成 md5 哈希值
 * @param str 要哈希的字符串
 * @returns 哈希值
 */
export function md5(str: string) {
  const hash = crypto.createHash('md5');
  hash.update(str);
  return hash.digest('hex');
}

/**
 * 获取当前日期的数字格式 (YYYYMMDD)
 * @returns 数字格式的日期，如 20250608
 */
export function getCurrentDateNumber(): number {
  const date = new Date();
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return Number(`${year}${month}${day}`);
}

/**
 * 将数组按照指定大小进行分片
 * @param array 要分片的数组
 * @param chunkSize 每个分片的大小
 * @returns 分片后的二维数组
 */
export function chunkArray<T>(array: T[], chunkSize: number): T[][] {
  const chunks: T[][] = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    chunks.push(array.slice(i, i + chunkSize));
  }
  return chunks;
}

/**
 * 创建雪花ID
 * @returns ID值
 */
export function generateSnowId() {
  return snowflake.generate();
}

/**
 * 生成指定范围内的随机整数
 * @param min 最小值（包含）
 * @param max 最大值（包含）
 * @returns 范围内的随机整数
 */
export function randomBetween(min: number, max: number): number {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
 * 生成指定位数的随机数字字符串
 * @param digits 位数
 * @returns 指定位数的随机数字字符串（可包含前导0）
 */
export function generateRandomNumber(digits: number): string {
  if (digits <= 0) {
    throw new Error('位数必须大于0');
  }

  let result = '';
  for (let i = 0; i < digits; i++) {
    result += Math.floor(Math.random() * 10);
  }

  return result;
}

/**
 * 格式化日期
 * @param dateString 日期字符串
 * @returns 格式化后的日期字符串
 */
export function formatDate(dateString?: Date, format: string = 'YYYY-MM-DD HH:mm:ss') {
  if (!dateString) return '';
  return dayjs(dateString).utc().format(format);
}

/**
 * 批量执行函数，控制并发数量
 * @param tasks 任务函数数组，每个函数返回Promise
 * @param batchSize 每批执行的任务数量
 * @returns 返回所有任务的执行结果
 */
export async function executeBatches<T = any>(tasks: (() => Promise<T>)[], batchSize: number): Promise<PromiseSettledResult<T>[]> {
  const results: PromiseSettledResult<T>[] = [];

  // 分批处理任务
  for (let i = 0; i < tasks.length; i += batchSize) {
    const batch = tasks.slice(i, i + batchSize);
    console.log(`执行第 ${Math.floor(i / batchSize) + 1} 批任务，共 ${batch.length} 个任务`);

    // 使用 Promise.allSettled 确保无论成功失败都继续执行
    const batchResults = await Promise.allSettled(batch.map((task) => task()));

    results.push(...batchResults);

    // 可选：批次间添加延迟
    if (i + batchSize < tasks.length) {
      await new Promise((resolve) => setTimeout(resolve, 100));
    }
  }

  return results;
}

/**
 * 将数字转换为中文单位格式（千、万、亿）
 * @param num 要转换的数字
 * @returns 转换后的字符串，如 "1.23万"、"45.67亿"
 */
export function formatNumberToChinese(num: number): string {
  if (num === 0) return '0';

  const absNum = Math.abs(num);
  const sign = num < 0 ? '-' : '';

  if (absNum >= 100000000) {
    // 亿
    return sign + (absNum / 100000000).toFixed(2).replace(/\.?0+$/, '') + '亿';
  } else if (absNum >= 10000) {
    // 万
    return sign + (absNum / 10000).toFixed(2).replace(/\.?0+$/, '') + '万';
  } else if (absNum >= 1000) {
    // 千
    return sign + (absNum / 1000).toFixed(2).replace(/\.?0+$/, '') + '千';
  } else {
    // 小于1000的数字，保留两位小数
    return sign + absNum.toFixed(2).replace(/\.?0+$/, '');
  }
}

export const isDef = (value: any) => {
  return value !== undefined && value !== null;
};

/**
 * 获取指定日期是周几（返回中文）
 * @param date 日期对象或日期字符串
 * @returns 中文星期，如 "周一"、"周日"
 */
export function getDayOfWeekChinese(date: Date | string): string {
  const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  return weekDays[dayjs(date).day()];
}
